#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright @ 2014 OPS, Qunar Inc. (qunar.com)
#
# Author: tingfang.bao <tingfang.bao@qunar.com>
# DateTime: 15-3-6 下午5:05
"""
flask的信号机制，需要blinker库的支持

信号：通过信号触发操作，实现解耦．允许发送者通知订阅者，某些事情发生了，并不提倡订阅者可以修改数据，只是通知他们好了．
有些信号与内置装饰器作用相近，比如
信号：request_started=>before_request()
但还是有区别的
before_request(): 按指定顺序执行，可以中断http请求
request_started信号：所有的信号handler是无序执行的，并且不能修改数据

1. 订阅信号
调用信号对象上的connect(handler, sender)方法．
    handler：一个方法，事件发生时，执行这个方法
    sender: 指定发送者

2. 退订
调用信号对象上的disconnect()

对于核心的flask信号，发送者都是app, 订阅信号时,必须制定发送者，否则会接受所有的事件，无论是谁发送的。
"""

from flask import Flask, template_rendered, render_template
from contextlib import contextmanager

app = Flask(__name__)


@contextmanager
def captured_template(app, templates, **extra):
    def record(sender, template, context, **kwargs):
        print extra
        templates.append((template, context))

    template_rendered.connect(record, app)
    try:
        yield templates
    finally:
        template_rendered.disconnect(record, app)


@app.route('/')
def index():
    return render_template('index.html', items=10)


@app.route('/faq')
def faq():
    return render_template("faq.html")


templates = []
# 记录了整个测试过程中所有页面访问情况
with captured_template(app, templates, user="baotingfang"):
    rv = app.test_client().get('/')
    assert rv.status_code == 200
    assert len(templates) == 1
    template, context = templates[0]
    assert template.name == 'index.html'
    assert context['items'] == 10

    rv = app.test_client().get('/faq')
    assert rv.status_code == 200
    assert len(templates) == 2
